package org.sl.flvplayer.elements {
	import org.sl.flvplayer.controls.PlayerLogic;
	import org.sl.flvplayer.data.Config;
	import org.sl.flvplayer.elements.ControllerElement;
	import org.sl.flvplayer.flyweights.FWPlayerCommand;
	import org.sl.flvplayer.helper.TimeCode;
	import org.sl.flvplayer.view.PlayerScreen;

	import flash.display.MovieClip;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.ColorTransform;
	import flash.geom.Rectangle;
	import flash.text.TextField;
	import flash.text.TextFieldAutoSize;
	import flash.text.TextFieldType;

	/**
	 * Provides controlls for the seekbar like drag and drop of the seekbutton or the clickable seekbar.</br>
	 * It also displays the time elapsed and total time of the current video.
	 * 
	 * @package org.sl.flvplayer.elements
	 * @author Dan
	 * @version
	 * @see org.sl.flvplayer.elements.IControllerElement
	 * @see org.sl.flvplayer.controls.Controller
	 */ 
	public class SeekControllerElement extends ControllerElement {	
		
		private var seekBar_mc : MovieClip;
		private	var seek_mc : MovieClip;
		private	var loader_mc : MovieClip;
		private	var color_mc : MovieClip;
		private var progress_mc : MovieClip;
		private var background_mc : MovieClip;
		private var seekBackground_mc : MovieClip;
		private var seekPos : Number;
		private var currentPlayTime : Number;
		private var videoDuration : Number;
		
		//constrain proportions
		private var seekScale : Number;
		
		private var bytesTotal : Number;
		private var bytesLoaded : Number;
		
		//original width of the seekbar  is needed for calculating the scalefactor 
		private var seekBarOriginalWidth : Number;		
		private var timeCode : TimeCode = new TimeCode();
		
		/**
		 * Current time of the video.
		 */
		public var displayCT : TextField = new TextField();
		
		/**
		 * The overall videoduration.
		 */
		public var displayPT : TextField = new TextField();

		/**
		 * SeekControllerElement constructor enables mouseinteraction for the subelements of the btnSeek element. 
		 * 
		 * @param p_allowScale indicates whether the element is scaleable
		 */
		public function SeekControllerElement(p_allowScale : Boolean = false) {
			super();
			allowScale = p_allowScale;
			mouseChildren = true;	
		}

		/**
		 * Sets the width of the btnSeek element. Furthermore adjust positioning and width of the subelements depending on the total width of the btnSeek element. 
		 * 
		 * @param p_width width of the <code>btnSeek</code> element
		 */
		override public function set width(p_width : Number) : void {					
			background_mc.width = p_width;
			
			seekBar_mc.width = seekBar_mc.x + background_mc.width - (displayCT.width * 4);	
			seekBackground_mc.width = seekBar_mc.x + background_mc.width - (displayCT.width * 4);
			// scalefactor for the seekbar			
			seekScale = seekBar_mc.width / seekBarOriginalWidth ;
			
			displayPT.x = background_mc.x + background_mc.width - (displayPT.width * 1.5);
			displayPT.y = background_mc.y + (displayPT.height / 8);
			
			displayCT.x = displayPT.x - displayCT.width - (displayCT.width / 10);
			displayCT.y = background_mc.y + (displayCT.height / 8);	
			
			loader_mc.width = (bytesLoaded / bytesTotal) * seekBar_mc.width;
			progress_mc.width = (currentPlayTime / videoDuration) * seekBar_mc.width;		 					
		}
		
		/**
		 */
		override public function addSkin(p_skin : MovieClip, p_type : String) : void {
			var obj : Object = {skin:p_skin, type:p_type};
			skinList.push(obj);
		}
		
		/**
		 */
		override public function showSkin(p_type : String) : void {
			if (aktSkin) removeChild(aktSkin);
			for (var i:String in skinList) {
				if (skinList[i].type == p_type) {
					aktSkin = addChild(skinList[i].skin);
				}
			}
			initMovieClips();
		}
		
		/**
		 * Initializes all the parts of the seekbar which are used for user interaction.  
		 */
		private function initMovieClips() : void {		
			background_mc = MovieClip(aktSkin).getChildByName("background") as MovieClip;	
			
			seekBar_mc = MovieClip(aktSkin).getChildByName("seekBar") as MovieClip;		
			seekBar_mc.addEventListener(MouseEvent.CLICK, onMouseClick);
			
			seekBackground_mc = MovieClip(aktSkin).getChildByName("seekBackground") as MovieClip;
			
			loader_mc = MovieClip(aktSkin).getChildByName("loader") as MovieClip;
			loader_mc.width = 0;
			
			color_mc = loader_mc.getChildByName("color") as MovieClip;	
								
			progress_mc = MovieClip(aktSkin).getChildByName("progress") as MovieClip;
			progress_mc.width = 0;	
			
			displayCT.type = TextFieldType.DYNAMIC;
			displayCT.autoSize = TextFieldAutoSize.LEFT;
			displayCT.selectable = false;
			displayCT.scaleX = 0.9;
			displayCT.scaleY = 0.9;
			displayCT.text = "00:00 /";					
		
			displayPT.type = TextFieldType.DYNAMIC;
			displayPT.autoSize = TextFieldAutoSize.RIGHT;
			displayPT.selectable = false;
			displayPT.scaleX = 0.9;
			displayPT.scaleY = 0.9;
			displayPT.text = "00:00";	
			
			addChild(displayCT);
			addChild(displayPT);			
	
			seekBarOriginalWidth = seekBar_mc.width;
		}
				
		/**
		 *  Initializes the seekbutton.</br>
		 *  It`s initialized separatedly when playback is startet to prevent drag n drop and seeking while nothing is playing.
		 */
		public function initSeekButton() : void {
			seek_mc = MovieClip(aktSkin).getChildByName("seek") as MovieClip;
			seek_mc.x = seekBar_mc.x;
			seek_mc.y = seekBar_mc.y + seekBar_mc.height / 2;	
			seek_mc.addEventListener(MouseEvent.MOUSE_DOWN, mouseDown);	
			seek_mc.addEventListener(Event.ENTER_FRAME, seek);
		}	
				
		/**
		 * Seekbutton`s mouseDrag method.</br> 
		 * Drag and drop of the seekbutton is only possible when playback of the video has been triggered.
		 * 
		 * @param p_event
		 */
		private function mouseDown(p_event : MouseEvent) : void {
			if(PlayerScreen.getInstance().source.isStarted) {
				stage.addEventListener(MouseEvent.MOUSE_UP, mouseUp);
				var seekRec : Rectangle = new Rectangle(seekBar_mc.x, seek_mc.y, seekBar_mc.width, 0);
				seek_mc.startDrag(false, seekRec);	
				seek_mc.removeEventListener(Event.ENTER_FRAME, seek);	
			}		
		}
		
		/**
		 * Handles the mouseUp event.
		 * 
		 * @param p_event
		 */
		private function mouseUp(p_event : MouseEvent) : void {					
			mouseInteractionData();
			seek_mc.stopDrag();
			seek_mc.addEventListener(Event.ENTER_FRAME, seek);
			stage.removeEventListener(MouseEvent.MOUSE_UP, mouseUp);
		}
		
		/**
		 * MouseClick handler.
		 * 
		 * @param p_event
		 */
		private function onMouseClick(p_event : MouseEvent) : void {						
			if(PlayerScreen.getInstance().source.isStarted) {
				mouseInteractionData();
			}
		}
		
		/**
		 * Loadingbar shows the loading progress of the video.  
		 * 
		 * @param p_event
		 */	
		private function loadingHandler(p_event : Event) : void {	
			bytesTotal = PlayerScreen.getInstance().source.ns.bytesTotal;			
			bytesLoaded = PlayerScreen.getInstance().source.ns.bytesLoaded;
			loader_mc.width = (bytesLoaded / bytesTotal) * seekBar_mc.width;	
			if (!Config.getInstance().streamingMode && bytesTotal == bytesLoaded) {
				loader_mc.removeEventListener(Event.ENTER_FRAME, loadingHandler);
			}			
		}
		
		
		/**
		 * Provides data for seekoperations and the current playtime.
		 */	
		private function seek(p_event:Event) : void {
			currentPlayTime = PlayerScreen.getInstance().source.ns.time;
			displayCT.text = timeCode.getTC(currentPlayTime) + " /";		 
			progress_mc.width = (currentPlayTime / videoDuration) * seekBar_mc.width;
			seek_mc.x = progress_mc.width + seekBar_mc.x;
			vidDuration(PlayerScreen.getInstance().source.videoDuration);
		}
		
		/**
		 * Calculates the seek position and sets the SEEK command.   
		 */	
		private function mouseInteractionData() : void {
		/*
			if(seekBar_mc.mouseX < 0) { 
				seekPos = 0;
			}
				else if(seekBar_mc.mouseX > seekBar_mc.width) {
				seekPos = videoDuration;
			} else {
				seekPos = seekBar_mc.mouseX * (videoDuration / seekBar_mc.width) * seekScale;
			}
			 * 
			 */
			seekPos = seekBar_mc.mouseX * (videoDuration / seekBar_mc.width) * seekScale;
			PlayerLogic.getInstance().command(new FWPlayerCommand(FWPlayerCommand.SEEK, this, [seekPos]));
		}
		
		/**
		 * Changes the color of color_mc and the progress_mc bar.
		 * 
		 * @param p_color
		 */	
		private function color(p_color : Number) : void {
			var	colorTransform : ColorTransform = color_mc.transform.colorTransform;			
			colorTransform.color = p_color;
			color_mc.transform.colorTransform = colorTransform;
			progress_mc.transform.colorTransform = colorTransform;
		}
		
		/**
		 * Sets the total playtime of the video.
		 * 
		 * @param dur videoduration
		 */	
		public function vidDuration(duration : Number) : void {	
			if(duration) {
				videoDuration = duration;	
				displayPT.text = timeCode.getTC(videoDuration);
			}
		}
			
		/**
		 * Initializes the loader and sets the color of the loader and the seekbar.
		 */		
		public function initLoader() : void {
			color(Config.getInstance().highlightcolor);	
			loader_mc.addEventListener(Event.ENTER_FRAME, loadingHandler);		
		}	
	}
}
